
/*
 * @项目名称: 模板开发
 * @FilePath: /meek/src/geometry/cube.js
 * @Author: zhangning@datatang.com
 * @Date: 2019-11-14T17:59:02+08:00
 * @LastEditors: yangxianghong@datatang.com
 * @LastEditTime: 2023-07-12 10:56:05
 * Copyright (c) 2018-2022 
 */
                                                    
/**
 * Created by zypc on 2016/11/13.
 */

import Geometry from './geometry'
import { ExtentUtil } from './support/extentutil'
import { CubeUtil, deepClone } from './support/cubeutil'
import Extent from './extent'
import Polygon from './polygon'
import { centerLinearRingss, linearRingss } from './support/interpolate'
import { linearRingssAreOriented, orientLinearRingss } from './support/orient'
import coordinate from '../utils/coordinate';
import { distance, pointDistanceToSegment, getProjectionPointOnLine } from './support/geometryutil'

/**
 * 矩形类和数据结构
 *
 * @class Extent
 * @extends Geometry
 * @module geometry
 * @constructor
 * @example
 *
 *  var rect = new Datatang.Cube(100, 100, 100)
 */
export default class Cube extends Geometry {

  /**
   * 构造函数，构建一个extent对象
   *
   * @param xmin {Number}
   * @param ymin {Number}
   * @param xmax {Number}
   * @param ymax {Number}
   *
   */
  constructor(coordinates) {
    super()

    this._rings = []

    this.stride = 2

    this.cubeMode = Cube.cubeMode;//1标准立方体，2前后矩形不等立方体 3//面梯形
    /**
     * 记录当前多边形内点更新的次数
     * @type {number}
     * @private
     */
    this._flatInteriorPointRevision = -1

    /**
     * 缓存当前多边形内点
     * @type {null}
     * @private
     */
    this._flatInteriorPoint = null

    /**
     * 立方体被拖出的方向(左边或右边)
     */
    this._isLeft = null;

    /**
     * 当前需要高亮的面
     */
    this._currentFace = null;

    this._direction = null;

    this.setCoordinates(coordinates)
  }

  set isLeft(value) {
    if (this._isLeft !== value) {
      if (this.direction === 4) {
        this.direction = 1
      } else if (this.direction === 1) {
        this.direction = 4
      }
    }

    this._isLeft = value;

  }

  get isLeft() {
    return this._isLeft;
  }

  set currentFace(value) {
    this._currentFace = value
    this.changed()
  }

  get currentFace() {
    return this._currentFace
  }

  set direction(value) {
    console.log("in set direction", value)
    this._direction = value;
    this.changed()
  }

  get direction() {
    return this._direction;
  }

  /**
   * 获取Geometry的类型
   *
   * @property geometryType
   * @returns {String}
   */
  get geometryType() { return Geometry.CUBE }

  /**
   * 计算x轴的中心坐标
   *
   * @property centerX
   * @type {Number}
   */
  get centerX() { return (this.xmax + this.xmin) / 2 }

  /**
   * 计算Y轴的中心坐标
   *
   * @property centerY
   * @type {Number}
   */
  get centerY() { return (this.ymax + this.ymin) / 2 }

  /**
   * 计算最小外接矩形的宽
   *
   * @property width
   * @returns {Number}
   */
  get width() {
    return Math.abs(
        this.rings[0][0][2][0] - this.rings[0][0][1][0]
      );
  }

  /**
   * 计算最小外接矩形的高
   *
   * @property height
   * @returns {Number}
   */
  get height() {
    return Math.abs(
        this.rings[0][0][0][1] - this.rings[0][0][1][1]
      );
  }

  /**
   * 计算复合多边形的最小外界矩形
   * 注意：这里所求出来的是多个多边形的最小外界矩形，既一个能包裹所有
   * 多边形的矩形
   *
   * @returns {Extent|null}
   */
  get extent() {
    if (this._extent === null) {
      const allPolygonCoords = this.getCoordinates()
      // 计算最小外界矩形，只考虑外围环
      if (allPolygonCoords.length > 0) {
        let xmin = Number.POSITIVE_INFINITY
        let ymin = Number.POSITIVE_INFINITY
        let xmax = Number.NEGATIVE_INFINITY
        let ymax = Number.NEGATIVE_INFINITY

        allPolygonCoords.forEach(polyCoods => {
          let rings = polyCoods[0]
          if (!rings) {
            return ;
          }
          for (let ring of rings) {
            xmin = Math.min(xmin, ring[0])
            ymin = Math.min(ymin, ring[1])
            xmax = Math.max(xmax, ring[0])
            ymax = Math.max(ymax, ring[1])
          }
        })
        this._extent = new Extent(xmin, ymin, xmax, ymax)
      }
    }
    return this._extent
  }

  /**
   * 判断3d拉框是否绘制完成
   * @returns {Boolean}
  */
  get completed() {
    const coords = this.getCoordinates();
    return coords.length > 1;
  }

  getArea() {
    return this.width * this.height;
  }

  /**
   * 判断集合多边形是否包括指定 x 和 y
   * @param x
   * @param y
   * @returns {boolean}
   */
  containsXY(x, y) {
    const polygons = this.rings
    for (let i = 0, len = polygons.length; i < len; i++) {
      const onePolygon = this.getPolygon(i)
      if (onePolygon.containsXY(x, y)) {
        return true
      }
    }

    return false
  }
  /**
     * 获取标签显示的内点
     * 注意：复合多边形，标签显示的位置，只显示在第一个图形上
     * @returns {*}
     */
  getFlatInteriorPoint() {
    if (this._flatInteriorPointRevision !== this.revision) {
      this._flatInteriorPointRevision = this.revision

      /*
      const polygons = this.rings
      let flatCoordinates = []
      let endss = []

      const orderArray = []

      polygons.forEach(polygon => {
        const outRings = polygon[0]
        orderArray.push(outRings)
      })

      orderArray.sort((arr1, arr2) => arr1.length - arr2.length)

      let lastLen = 0
      orderArray.forEach(arr => {
        const currLen = arr.length * 2 + lastLen
        endss.push([currLen])
        lastLen = currLen

        arr.forEach(points => {
          flatCoordinates.push(points[0], points[1])
        })
      })

      const flatCenters = centerLinearRingss(flatCoordinates, 0, endss, this.stride)
      this._flatInteriorPoint = linearRingss(
        this.getOrientedFlatCoordinates(flatCoordinates, endss), 0, endss, this.stride,
        flatCenters)
      */
      this._flatInteriorPointRevision = this.revision

      const coords = this.getCoordinates();
      let minY = Infinity;
      let target;
      coords[0].forEach(coord => {
        coord.forEach(c => {
          if (c[1] < minY) {
            minY = c[1];
            target = c;
          }
        })
        
      })

      if (target) {
        this._flatInteriorPoint = [target[0], target[1]];
      }
    }


    return this._flatInteriorPoint
  }
  /**
   * 获得一个多边形对象
   * 
   * @method getPolygon
   * @param index 多边形的下标
   * @returns {Datatang.Polygon} 返回一个新的多边形对象
   */
  getPolygon(index) {
    if (index < 0 && this.rings.length < index) {
      return null
    }

    const coords = this.rings[index]
    let outRing = []
    let innerRing = []
    coords.forEach(rings => {
      rings.forEach(points => {
        innerRing.push([points[0], points[1]])
      })

      outRing.push(innerRing)
      innerRing = []
    })

    const polygon = new Polygon(outRing)
    return polygon
  }


  /**
   * 移动矩形通过x，y值
   *
   * @method move
   * @param x {Number}
   * @param y {Number}
   */
  move(x = 0, y = 0, opts) {
    let beyond
    if (opts) {
      if (opts.beyond) {
        beyond = opts.beyond
      }
    }

    const oldCoordinates = this.getCoordinates();

    let newCoordinates = []

    for (let coords of oldCoordinates) {
      const oldCoords = coords[0]
      const newCoords = [[]]
      newCoords[0] = CubeUtil.moveExtent(oldCoords, x, y);
      newCoordinates.push(newCoords)
    }

    if (beyond) {
      for (let coords of newCoordinates) {
        for (let coord of coords[0]) {
          if (
            coord[0] < beyond.xmin ||
            coord[0] > beyond.xmax ||
            coord[1] < beyond.ymin ||
            coord[1] > beyond.ymax
          ) {
            return;
          }
        }
      }
    }

    this.setCoordinates(newCoordinates);
  }

  /**
   * 移动立方体的某个面（前面/后面）
   * @param {Number} x 
   * @param {Number} y 
   * @param {Object} opts 
   */
  moveFace(x = 0, y = 0, opts) {
    let beyond
    if (opts) {
      if (opts.beyond) {
        beyond = opts.beyond
      }
    }

    const oldCoordinates = this.getCoordinates();

    const currentFace = oldCoordinates[this.currentFace][0];
    const newFace = CubeUtil.moveExtent(currentFace, x, y);
    
    const newCoordinates = deepClone(oldCoordinates);
    newCoordinates[this.currentFace][0] = newFace

    if (newCoordinates.length > 1) {

      const points = CubeUtil.getPointsFromFrontAndBackFace(newCoordinates, this.isLeft)
    
      CubeUtil.updateCoordinatesFromPoints(
        newCoordinates,
        points,
        this.isLeft
      )
    }

    if (beyond) {
      for (let coords of newCoordinates) {
        for (let coord of coords[0]) {
          if (
            coord[0] < beyond.xmin ||
            coord[0] > beyond.xmax ||
            coord[1] < beyond.ymin ||
            coord[1] > beyond.ymax
          ) {
            return;
          }
        }
      }
    }

    this.setCoordinates(newCoordinates);
  }

  /**
   * 设置多边形的边，如果设置了边，则需要重新计算
   * 外接矩形
   *
   * @method rings
   * @returns {Array}
   */
  get rings() {
    // if (this._rings.length === 0) {
    //   if (this.xmin !== 0 && this.ymin !== 0 && this.xmax !== 0 && this.ymax !== 0) {
    //     this._rings = ExtentUtil.minMaxToRing(this.xmin, this.ymin, this.xmax, this.ymax)
    //   }
    // }

    return this._rings
  }

  set rings(value) {
    this._rings = value
    // let extentArr = ExtentUtil.boundingSimpleExtent(value)
    // this.xmin = extentArr[0]
    // this.ymin = extentArr[1]
    // this.xmax = extentArr[2]
    // this.ymax = extentArr[3]
  }

  /**
   * 获取图形的坐标数据
   *
   * @method getCoordinates
   * @returns {[*,*]}
   */
  getCoordinates() {
    // if (this._rings.length === 0) {
    //   if (this.xmin !== 0 && this.ymin !== 0 && this.xmax !== 0 && this.ymax !== 0) {
    //     this._rings = ExtentUtil.minMaxToRing(this.xmin, this.ymin, this.xmax, this.ymax)
    //   }
    // }
    return this._rings
  }

  /**
   * 设置坐标数据
   *
   * @method setCoordinates
   * @param coordinates
   */
  setCoordinates(coordinates) {
    this.rings = coordinates
    this._extent = null
    // let extentArr = ExtentUtil.boundingSimpleExtent(coordinates)
    // this.xmin = extentArr[0]
    // this.ymin = extentArr[1]
    // this.xmax = extentArr[2]
    // this.ymax = extentArr[3]

    this.changed()
  }

  /**
   * 获取点位于图形坐标点的下标
   *
   * @method getCoordinateIndex
   * @param coord {Array}
   * @returns {Number}
   */
  getCoordinateIndex(coord) {
    return this.getCoordinates().findIndex(points =>
      points[0] === coord[0] && points[1] === coord[1]
    )
  }
  /**
   * 根据坐标值计算复合多边形的点下标
   *
   * @method getCoordinateIndex
   * @param coord 坐标值，[x, y]结构
   * @returns {
   *    {
   *      polygonIndex: number 位于第几个多边形上 ,
   *      ringIndex: number 位于多边形第几个环上,
   *      index: number 位于环上第几个顶点上
   *     }
   *   }
   */
  getCoordinateIndex(coord) {
    const polygonCoods = this.getCoordinates()
    for (let ii = 0, iiLen = polygonCoods.length; ii < iiLen; ii++) {
      const coords = polygonCoods[ii]

      for (let i = 0, len = coords.length; i < len; i++) {
        const rings = coords[i]
        for (let j = 0, jLen = rings.length; j < jLen; j++) {
          const point = rings[j]
          if (point[0] === coord[0] && point[1] === coord[1]) {
            return {
              polygonIndex: ii,
              ringIndex: i,
              index: j
            }
          }
        }
      }
    }

    return {
      polygonIndex: -1,
      ringIndex: -1,
      index: -1
    }
  }
  /**
   * 计算复合多边形顺时针坐标
   * @param flatCoordinates
   * @param endss
   * @returns {*}
   */
  getOrientedFlatCoordinates(flatCoordinates, endss) {
    let orientedFlatCoordinates

    if (linearRingssAreOriented(flatCoordinates, 0, endss, this.stride)) {
      orientedFlatCoordinates = flatCoordinates
    } else {
      orientedFlatCoordinates = [...flatCoordinates]
      orientedFlatCoordinates.length = orientLinearRingss(orientedFlatCoordinates,
        0, endss, this.stride)
    }

    return orientedFlatCoordinates
  }
  /**
   * 得到最后一个点的坐标，显示表单
   *
   * @param {Number} offsetX x的偏移量
   * @param {Number} offsetY y的偏移量
   * @returns {[*,*]}
   */
  getFormShowPosition(offsetX = 0, offsetY = 0) {
    const coordinates = this.getCoordinates()[0][0]

    if (coordinates.length === 0) {
      return
    }

    const lastPoint = coordinates[coordinates.length - 2]
    return [lastPoint[0] - offsetX, lastPoint[1] - offsetY]
  }
  /**
   * 克隆矩形框
   *
   * @method clone
   * @returns {Extent}
   */
  clone() {
    const cube = new Cube(this.getCoordinates())
    cube.isLeft = this.isLeft;
    cube.cubeMode = this.cubeMode;
    return cube;
  }

  /**
   * 获取可见面的json数据
   * @return {Object}
   */
  getAreaOfVisibleFaces() {
    const coordinates = this.getCoordinates();
    let result = []
    
    coordinates.forEach((coords, index) => {
      const description = CubeUtil.getDescriptionOfFace(this, index);
      const isVisible = CubeUtil.isFaceVisible(this, index, description);
      if (index !== 3 && isVisible) {
        const area = CubeUtil.getAreaOfFace(coords[0]);
        result.push({
          description,
          area
        });
      }
    });

    return result;
  }

  readCoordinates(coords) {
    /*
    const coordinates = coords.map(coord => {
      return coord.coordinates;
    });

    if (coordinates.length > 1) {
      this.isLeft = coordinates[0][0][0][0] === coordinates[1][0][0][0];
    }

    this.setCoordinates(coordinates);
    */
    const faces = {}
    coords.forEach(coord => {
      faces[coord.face] = coord.coordinates;
    });

    /*

    // 不足六个面，从三个必填面算出第八个点
    const x = faces["left"][0][3][0] + (faces["top"][0][3][0] - faces["top"][0][2][0]);
    const y = faces["top"][0][3][1] + (faces["left"][0][3][1] - faces["left"][0][2][1]);
    
    // 计算其他三个面（即便有也重新计算—）
    faces["bottom"] = [
      [
        [faces["back"][0][0][0], faces["back"][0][0][1]],
        [faces["left"][0][3][0], faces["left"][0][3][1]],
        [x, y],
        [faces["back"][0][3][0], faces["back"][0][3][1]]
      ]
    ]

    faces["right"] = [
      [
        [faces["back"][0][3][0], faces["back"][0][3][1]],
        [faces["back"][0][2][0], faces["back"][0][2][1]],
        [faces["top"][0][3][0], faces["top"][0][3][1]],
        [x, y]
      ]
    ]

    faces["front"] = [
      [
        [x,y],
        [faces["top"][0][3][0], faces["top"][0][3][1]],
        [faces["top"][0][2][0], faces["top"][0][2][1]],
        [faces["left"][0][3][0], faces["left"][0][3][1]]
      ]
    ]
    */

    let coordinates = null;
    if (faces["left"]) {
      coordinates = [faces["back"], faces["left"], faces["top"], faces["front"], faces["right"], faces["bottom"]]
    } else {
      coordinates = [faces["back"]];
    }
    this.isLeft = true;
    this.setCoordinates(coordinates)
  }

  exportCoordinates() {
    const coordinates = this.getCoordinates();
    let result = [];
    coordinates.forEach((coords, index) => {
      const face = CubeUtil.getDescriptionOfFace(this, index)
      result.push({
        face,
        visible: CubeUtil.isFaceVisible(this, index, face),
        coordinates: coords
      })
    });
    return result;
  }

  /**
   * 用于计算和更新立方体的顶点
   *
   * @param p 平行四边形对象
   * @param vertex 新移动的点
   * @param oldVertex 上次移动的点
   * @param dragSegment 数据对象
   * @returns {*} 返回新的点集合（3维数组）
   */
  static updateCoordinatesForModification(geometry, segmentData, coordinates, vertex, oldEditedVertex, evt, extent) {
    const handlers = CubeUtil.modificationHandlers;

    const cubeMode = geometry.cubeMode || Cube.cubeMode;

    const newCoordindates = deepClone(coordinates)

    // ctrl键时，从左/右方向拖出立方体
    if (evt.originalEvent.ctrlKey === true) {
      handlers["ctrl"].call(geometry, segmentData, newCoordindates, vertex);
    } else {
      const shiftKey = evt.originalEvent.shiftKey;
      if (segmentData.polygonIndex === 0) {
        // 如果拖动第一面
        const flag = handlers[cubeMode]["front"].call(geometry, newCoordindates, vertex, segmentData, extent, shiftKey);
        if (!flag) {
          return;
        }
      }

      if (segmentData.polygonIndex > 0 ) {
        const flag = handlers[cubeMode]["back"].call(geometry, newCoordindates, vertex, segmentData, extent, shiftKey)
        if (!flag) {
          return;
        }
      }
    }


    /*
    if (segmentData.polygonIndex >= 2) {
      return;
    }
    */
    /*
    if (Cube.cubeMode === 1) {
      // if (segmentData.polygonIndex === 0 && segmentData.isVertex) {
      //   if (segmentData.index === 0 || segmentData.index === 3) {
      //     coordinates[segmentData.polygonIndex][segmentData.ringIndex][0][1] = vertex[1]
      //     coordinates[segmentData.polygonIndex][segmentData.ringIndex][3][1] = vertex[1]
      //     if (coordinates[1]) {
      //       coordinates[1][segmentData.ringIndex][0][1] = vertex[1]
      //     }
      //   } else {
      //     return
      //   }
      // }
      // if (segmentData.index === 0 && segmentData.isVertex) {
      //   coordinates[segmentData.polygonIndex][segmentData.ringIndex][0][1] = vertex[1]
      // }
      if (segmentData.index === 0 && !segmentData.isVertex) {
        if (evt.originalEvent.ctrlKey === true) {
          if (segmentData.polygonIndex !== 0) {
            return
          }
          if (vertex[0] >= coordinates[0][0][0][0]) {
            return;
          }
          const newPolygon = [[]]
          coordinates[1] = newPolygon
          coordinates[1][0][0] = coordinates[segmentData.polygonIndex][segmentData.ringIndex][0]
          coordinates[1][0][1] = coordinates[segmentData.polygonIndex][segmentData.ringIndex][1]
          if (coordinates[segmentData.polygonIndex][segmentData.ringIndex][1][1] - 50 < 0) {
            coordinates[1][0][2] = [vertex[0], 0];
            coordinates[1][0][3] = [vertex[0], coordinates[segmentData.polygonIndex][segmentData.ringIndex][0][1] - coordinates[segmentData.polygonIndex][segmentData.ringIndex][1][1]];
          } else {
            coordinates[1][0][2] = [vertex[0], coordinates[segmentData.polygonIndex][segmentData.ringIndex][1][1] - 50]
            coordinates[1][0][3] = [vertex[0], coordinates[segmentData.polygonIndex][segmentData.ringIndex][0][1] - 50]
          }
        } else {

          if (vertex[0] >= coordinates[0][0][3][0]) {
            return;
          }
          
          if (coordinates[1]) {
            if (segmentData.polygonIndex === 0) {
              if (coordinates[0][0][3][0] === coordinates[1][0][0][0]) {
                if (vertex[0] >= coordinates[0][0][2][0]) {
                  return;
                }
              }
              if (coordinates[0][0][0][0] === coordinates[1][0][0][0]) {
                if (
                  vertex[0] <= coordinates[1][0][3][0] ||
                  vertex[0] >= coordinates[0][0][3][0]
                ) {
                  return;
                }
              }
            }
            if (coordinates[0][0][0][0] === coordinates[1][0][0][0]) {
              coordinates[1][segmentData.ringIndex][0][0] = vertex[0]
              coordinates[1][segmentData.ringIndex][1][0] = vertex[0]
            }
          }
          coordinates[segmentData.polygonIndex][segmentData.ringIndex][0][0] = vertex[0]
          coordinates[segmentData.polygonIndex][segmentData.ringIndex][1][0] = vertex[0]
        }
      }

      // if (segmentData.index === 1 && segmentData.isVertex) {
      //   coordinates[segmentData.polygonIndex][segmentData.ringIndex][1][1] = vertex[1]
      // }
      if (segmentData.index === 1 && segmentData.polygonIndex === 0 && !segmentData.isVertex) {
        if (coordinates[1]) {
          let newY = coordinates[1][segmentData.ringIndex][2][1] + vertex[1] - coordinates[segmentData.polygonIndex][segmentData.ringIndex][1][1];
          if (newY < 0) {
            newY = coordinates[1][segmentData.ringIndex][1][1] - coordinates[1][segmentData.ringIndex][2][1]
            coordinates[1][segmentData.ringIndex][1][1] = newY
            coordinates[segmentData.polygonIndex][segmentData.ringIndex][2][1] = newY
            coordinates[segmentData.polygonIndex][segmentData.ringIndex][1][1] = newY
            coordinates[1][segmentData.ringIndex][2][1] = 0
          } else {
            coordinates[1][segmentData.ringIndex][2][1] = newY
            coordinates[1][segmentData.ringIndex][1][1] = vertex[1]
            coordinates[segmentData.polygonIndex][segmentData.ringIndex][2][1]  = vertex[1]
            coordinates[segmentData.polygonIndex][segmentData.ringIndex][1][1]  = vertex[1]
          }
        } else {
          coordinates[segmentData.polygonIndex][segmentData.ringIndex][1][1] = vertex[1]
          coordinates[segmentData.polygonIndex][segmentData.ringIndex][2][1] = vertex[1]
        }
      }

      if (segmentData.index === 2 && segmentData.polygonIndex === 1 && segmentData.isVertex) {
        if (vertex[1] >= coordinates[0][0][2][1]) {
          return;
        }
        if (coordinates[1]) {
          const height = coordinates[1][0][2][1] - coordinates[1][0][3][1];
          if (vertex[1] < height) {
            coordinates[segmentData.polygonIndex][segmentData.ringIndex][3][1] = 0;
            coordinates[segmentData.polygonIndex][segmentData.ringIndex][2][1] = height;
          } else {
            coordinates[segmentData.polygonIndex][segmentData.ringIndex][3][1] = coordinates[segmentData.polygonIndex][segmentData.ringIndex][3][1] + vertex[1] - coordinates[segmentData.polygonIndex][segmentData.ringIndex][2][1]
            coordinates[segmentData.polygonIndex][segmentData.ringIndex][2][1] = vertex[1]
          }
        }
      }
      if (segmentData.index === 2 && !segmentData.isVertex) {
        if (evt.originalEvent.ctrlKey === true) {
          if (segmentData.polygonIndex !== 0) {
            return
          }
          if (vertex[0] <= coordinates[0][0][3][0]) {
            return;
          }
          const newPolygon = [[]]
          coordinates[1] = newPolygon
          coordinates[1][0][0] = coordinates[segmentData.polygonIndex][segmentData.ringIndex][3]
          coordinates[1][0][1] = coordinates[segmentData.polygonIndex][segmentData.ringIndex][2]
          if (coordinates[segmentData.polygonIndex][segmentData.ringIndex][2][1] - 50 < 0) {
            coordinates[1][0][2] = [vertex[0], 0];
            coordinates[1][0][3] = [vertex[0], coordinates[segmentData.polygonIndex][segmentData.ringIndex][3][1] - coordinates[segmentData.polygonIndex][segmentData.ringIndex][2][1]];
          } else {
            coordinates[1][0][2] = [vertex[0], coordinates[segmentData.polygonIndex][segmentData.ringIndex][2][1] - 50]
            coordinates[1][0][3] = [vertex[0], coordinates[segmentData.polygonIndex][segmentData.ringIndex][3][1] - 50]
          }
        } else {
          if (vertex[0] <= coordinates[0][0][0][0]) {
            return;
          }

          // 拖动右侧面的边
          if (coordinates[1] && coordinates[0][0][3][0] === coordinates[1][0][0][0]) {
            if (segmentData.polygonIndex === 1 && coordinates[1]) {
              if (
                vertex[0] <= coordinates[1][0][0][0]
              ) {
                return;
              }
            }
            if (segmentData.polygonIndex === 0 && coordinates[1]) {
              if (
                vertex[0] >= coordinates[1][0][2][0] ||
                vertex[0] <= coordinates[0][0][1][0]
              ) {
                return;
              }
            }
          }
          if (coordinates[1] && coordinates[0][0][0][0] === coordinates[1][0][0][0]) {
            if (segmentData.polygonIndex === 0) {
              if (vertex[0] <= coordinates[0][0][0][0]) {
                return;
              }
            }
            if (segmentData.polygonIndex === 1) {
              if (vertex[0] >= coordinates[0][0][0][0]) {
                return;
              }
            }
          }
          if (segmentData.polygonIndex === 0 && coordinates[1]) {
            if (coordinates[0][0][0][0] === coordinates[1][0][0][0]) {
            } else {
              coordinates[1][segmentData.ringIndex][0][0] = vertex[0]
              coordinates[1][segmentData.ringIndex][1][0] = vertex[0]
            }
          }
          coordinates[segmentData.polygonIndex][segmentData.ringIndex][2][0] = vertex[0]
          coordinates[segmentData.polygonIndex][segmentData.ringIndex][3][0] = vertex[0]
        }
      }
      if (segmentData.index === 3 && segmentData.polygonIndex === 1 && segmentData.isVertex) {
        if (vertex[1] >= coordinates[0][0][3][1]) {
          return;
        }
        const height = coordinates[1][0][3][1] - coordinates[1][0][2][1];
        if (vertex[1] < height) {
          coordinates[segmentData.polygonIndex][segmentData.ringIndex][2][1] = 0;
          coordinates[segmentData.polygonIndex][segmentData.ringIndex][3][1] = height;
        } else {
          coordinates[segmentData.polygonIndex][segmentData.ringIndex][2][1] = coordinates[segmentData.polygonIndex][segmentData.ringIndex][2][1] + vertex[1] - coordinates[segmentData.polygonIndex][segmentData.ringIndex][3][1]
          coordinates[segmentData.polygonIndex][segmentData.ringIndex][3][1] = vertex[1]
        }
      }
      if (segmentData.index === 3 && segmentData.polygonIndex === 0 && !segmentData.isVertex) {
        if (coordinates[1]) {
          let newY = coordinates[1][segmentData.ringIndex][3][1] + vertex[1] - coordinates[segmentData.polygonIndex][segmentData.ringIndex][0][1]
          if (newY < 0) {
            newY = coordinates[1][segmentData.ringIndex][0][1] - coordinates[1][segmentData.ringIndex][3][1]
            coordinates[1][segmentData.ringIndex][3][1] = 0
            coordinates[1][segmentData.ringIndex][0][1] = newY
            coordinates[segmentData.polygonIndex][segmentData.ringIndex][0][1] = newY
            coordinates[segmentData.polygonIndex][segmentData.ringIndex][3][1] = newY
          } else {
            coordinates[1][segmentData.ringIndex][3][1] = coordinates[1][segmentData.ringIndex][3][1] + vertex[1] - coordinates[segmentData.polygonIndex][segmentData.ringIndex][0][1]
            coordinates[1][segmentData.ringIndex][0][1] = vertex[1]
            coordinates[segmentData.polygonIndex][segmentData.ringIndex][0][1] = vertex[1]
            coordinates[segmentData.polygonIndex][segmentData.ringIndex][3][1] = vertex[1]
          }
        } else {
          coordinates[segmentData.polygonIndex][segmentData.ringIndex][0][1] = vertex[1]
          coordinates[segmentData.polygonIndex][segmentData.ringIndex][3][1] = vertex[1]
        }
      }
    }
    if (Cube.cubeMode === 2) {
      if (segmentData.polygonIndex === 0 && segmentData.isVertex) {
        if (segmentData.index === 0 || segmentData.index === 3) {
          coordinates[segmentData.polygonIndex][segmentData.ringIndex][0][1] = vertex[1]
          coordinates[segmentData.polygonIndex][segmentData.ringIndex][3][1] = vertex[1]
          if (coordinates[1]) {
            coordinates[1][segmentData.ringIndex][0][1] = vertex[1]
          }
        } else {
          return
        }
      }
      if (segmentData.index === 0 && segmentData.isVertex) {
        coordinates[segmentData.polygonIndex][segmentData.ringIndex][0][1] = vertex[1]
      }
      if (segmentData.index === 0 && !segmentData.isVertex) {
        if (evt.originalEvent.ctrlKey === true) {
          if (segmentData.polygonIndex !== 0) {
            return
          }
          if (vertex[0] < coordinates[0][0][0][0]) {
            return;
          }

          const newPolygon = [[]]
          coordinates[1] = newPolygon
          coordinates[1][0][0] = coordinates[segmentData.polygonIndex][segmentData.ringIndex][0]
          coordinates[1][0][1] = coordinates[segmentData.polygonIndex][segmentData.ringIndex][1]
          if (coordinates[segmentData.polygonIndex][segmentData.ringIndex][1][1] - 50 < 0) {
            coordinates[1][0][2] = [vertex[0], 0];
            coordinates[1][0][3] = [vertex[0], coordinates[segmentData.polygonIndex][segmentData.ringIndex][0][1] - coordinates[segmentData.polygonIndex][segmentData.ringIndex][1][1]];
          } else {
            coordinates[1][0][2] = [vertex[0], coordinates[segmentData.polygonIndex][segmentData.ringIndex][1][1] - 50]
            coordinates[1][0][3] = [vertex[0], coordinates[segmentData.polygonIndex][segmentData.ringIndex][0][1] - 50]
          }
        } else {
          if (coordinates[1]) {
            if (coordinates[0][0][0][0] === coordinates[1][0][0][0]) {
              coordinates[1][segmentData.ringIndex][0][0] = vertex[0]
              coordinates[1][segmentData.ringIndex][1][0] = vertex[0]
            }
          }
          coordinates[segmentData.polygonIndex][segmentData.ringIndex][0][0] = vertex[0]
          coordinates[segmentData.polygonIndex][segmentData.ringIndex][1][0] = vertex[0]
        }
      }

      if (segmentData.index === 1 && segmentData.isVertex) {
        coordinates[segmentData.polygonIndex][segmentData.ringIndex][1][1] = vertex[1]
      }
      if (segmentData.index === 1 && segmentData.polygonIndex === 0 && !segmentData.isVertex) {
        coordinates[segmentData.polygonIndex][segmentData.ringIndex][1][1] = vertex[1]
        coordinates[segmentData.polygonIndex][segmentData.ringIndex][2][1] = vertex[1]
        if (coordinates[1]) {
          coordinates[1][segmentData.ringIndex][1][1] = vertex[1]
        }
      }

      if (segmentData.index === 2 && segmentData.isVertex) {
        coordinates[segmentData.polygonIndex][segmentData.ringIndex][2][1] = vertex[1]
      }
      if (segmentData.index === 2 && !segmentData.isVertex) {
        if (evt.originalEvent.ctrlKey === true) {
          if (segmentData.polygonIndex !== 0) {
            return
          }
          const newPolygon = [[]]
          coordinates[1] = newPolygon
          coordinates[1][0][0] = coordinates[segmentData.polygonIndex][segmentData.ringIndex][3]
          coordinates[1][0][1] = coordinates[segmentData.polygonIndex][segmentData.ringIndex][2]
          if (coordinates[segmentData.polygonIndex][segmentData.ringIndex][2][1] - 50 < 0) {
            coordinates[1][0][2] = [vertex[0], 0];
            coordinates[1][0][3] = [vertex[0], coordinates[segmentData.polygonIndex][segmentData.ringIndex][3][1] - coordinates[segmentData.polygonIndex][segmentData.ringIndex][2][1]];
          } else {
            coordinates[1][0][2] = [vertex[0], coordinates[segmentData.polygonIndex][segmentData.ringIndex][2][1] - 50]
            coordinates[1][0][3] = [vertex[0], coordinates[segmentData.polygonIndex][segmentData.ringIndex][3][1] - 50]
          }
        } else {
          if (segmentData.polygonIndex === 0 && coordinates[1]) {
            if (coordinates[0][0][0][0] === coordinates[1][0][0][0]) {
            } else {
              coordinates[1][segmentData.ringIndex][0][0] = vertex[0]
              coordinates[1][segmentData.ringIndex][1][0] = vertex[0]
            }
          }
          coordinates[segmentData.polygonIndex][segmentData.ringIndex][2][0] = vertex[0]
          coordinates[segmentData.polygonIndex][segmentData.ringIndex][3][0] = vertex[0]
        }
      }
      if (segmentData.index === 3 && segmentData.isVertex) {
        coordinates[segmentData.polygonIndex][segmentData.ringIndex][3][1] = vertex[1]
      }
      if (segmentData.index === 3 && segmentData.polygonIndex === 0 && !segmentData.isVertex) {
        coordinates[segmentData.polygonIndex][segmentData.ringIndex][0][1] = vertex[1]
        coordinates[segmentData.polygonIndex][segmentData.ringIndex][3][1] = vertex[1]
        if (coordinates[1]) {
          coordinates[1][segmentData.ringIndex][0][1] = vertex[1]
        }
      }
      // coordinates[segmentData.polygonIndex][segmentData.ringIndex][segmentData.index] = vertex
      // if (segmentData.index === 0) {
      //   coordinates[segmentData.polygonIndex][segmentData.ringIndex][coordinates[segmentData.polygonIndex][segmentData.ringIndex].length - 1] = vertex
      // }
    }
    if (Cube.cubeMode === 3) {
      if (segmentData.index === 0 && segmentData.isVertex) {
        coordinates[segmentData.polygonIndex][segmentData.ringIndex][0][1] = vertex[1]
        if (coordinates[0][0][0][0] === coordinates[1][0][0][0]) {
          if (coordinates[1]) {
            coordinates[1][segmentData.ringIndex][0][1] = vertex[1]
          }
        }
      }
      if (segmentData.index === 0 && !segmentData.isVertex) {
        if (evt.originalEvent.ctrlKey === true) {
          if (segmentData.polygonIndex !== 0) {
            return
          }
          const newPolygon = [[]]
          coordinates[1] = newPolygon
          coordinates[1][0][0] = coordinates[segmentData.polygonIndex][segmentData.ringIndex][0]
          coordinates[1][0][1] = coordinates[segmentData.polygonIndex][segmentData.ringIndex][1]
          if (coordinates[segmentData.polygonIndex][segmentData.ringIndex][1][1] - 50 < 0) {
            coordinates[1][0][2] = [vertex[0], 0];
            coordinates[1][0][3] = [vertex[0], coordinates[segmentData.polygonIndex][segmentData.ringIndex][0][1] - coordinates[segmentData.polygonIndex][segmentData.ringIndex][1][1]];
          } else {
            coordinates[1][0][2] = [vertex[0], coordinates[segmentData.polygonIndex][segmentData.ringIndex][1][1] - 50]
            coordinates[1][0][3] = [vertex[0], coordinates[segmentData.polygonIndex][segmentData.ringIndex][0][1] - 50]
          }
        } else {
          if (coordinates[1]) {
            if (coordinates[0][0][0][0] === coordinates[1][0][0][0]) {
              coordinates[1][segmentData.ringIndex][0][0] = vertex[0]
              coordinates[1][segmentData.ringIndex][1][0] = vertex[0]
            }
          }
          coordinates[segmentData.polygonIndex][segmentData.ringIndex][0][0] = vertex[0]
          coordinates[segmentData.polygonIndex][segmentData.ringIndex][1][0] = vertex[0]
        }
      }

      if (segmentData.index === 1 && segmentData.isVertex) {
        coordinates[segmentData.polygonIndex][segmentData.ringIndex][1][1] = vertex[1]
        if (coordinates[0][0][0][0] === coordinates[1][0][0][0]) {
          if (coordinates[1]) {
            coordinates[1][segmentData.ringIndex][1][1] = vertex[1]
          }
        }
      }
      // if (segmentData.index === 1 && segmentData.polygonIndex === 0 && !segmentData.isVertex) {
      //   coordinates[segmentData.polygonIndex][segmentData.ringIndex][1][1] = vertex[1]
      //   coordinates[segmentData.polygonIndex][segmentData.ringIndex][2][1] = vertex[1]
      //   if (coordinates[1]) {
      //     coordinates[1][segmentData.ringIndex][1][1] = vertex[1]
      //   }
      // }

      if (segmentData.index === 2 && segmentData.isVertex) {
        const oldVal = coordinates[segmentData.polygonIndex][segmentData.ringIndex][2][1]
        coordinates[segmentData.polygonIndex][segmentData.ringIndex][2][1] = vertex[1]
        if (oldVal === coordinates[1][0][1][1] && coordinates[segmentData.polygonIndex][segmentData.ringIndex][2][0] == coordinates[1][0][1][0]) {
          if (coordinates[1]) {
            coordinates[1][0][1][1] = vertex[1]
          }
        }
      }
      if (segmentData.index === 2 && !segmentData.isVertex) {
        if (evt.originalEvent.ctrlKey === true) {
          if (segmentData.polygonIndex !== 0) {
            return
          }
          const newPolygon = [[]]
          coordinates[1] = newPolygon
          coordinates[1][0][0] = coordinates[segmentData.polygonIndex][segmentData.ringIndex][3]
          coordinates[1][0][1] = coordinates[segmentData.polygonIndex][segmentData.ringIndex][2]
          if (coordinates[segmentData.polygonIndex][segmentData.ringIndex][2][1] - 50 < 0) {
            coordinates[1][0][2] = [vertex[0], 0];
            coordinates[1][0][3] = [vertex[0], coordinates[segmentData.polygonIndex][segmentData.ringIndex][3][1] - coordinates[segmentData.polygonIndex][segmentData.ringIndex][2][1]];
          } else {
            coordinates[1][0][2] = [vertex[0], coordinates[segmentData.polygonIndex][segmentData.ringIndex][2][1] - 50]
            coordinates[1][0][3] = [vertex[0], coordinates[segmentData.polygonIndex][segmentData.ringIndex][3][1] - 50]
          }
        } else {
          if (segmentData.polygonIndex === 0 && coordinates[1]) {
            if (coordinates[0][0][0][0] === coordinates[1][0][0][0]) {
            } else {
              coordinates[1][segmentData.ringIndex][0][0] = vertex[0]
              coordinates[1][segmentData.ringIndex][1][0] = vertex[0]
            }
          }
          coordinates[segmentData.polygonIndex][segmentData.ringIndex][2][0] = vertex[0]
          coordinates[segmentData.polygonIndex][segmentData.ringIndex][3][0] = vertex[0]
        }
      }
      if (segmentData.index === 3 && segmentData.isVertex) {
        const oldVal = coordinates[segmentData.polygonIndex][segmentData.ringIndex][3][1]
        coordinates[segmentData.polygonIndex][segmentData.ringIndex][3][1] = vertex[1]
        if (oldVal === coordinates[1][0][0][1] && coordinates[segmentData.polygonIndex][segmentData.ringIndex][3][0] === coordinates[1][0][0][0]) {
          if (coordinates[1]) {
            coordinates[1][0][0][1] = vertex[1]
          }
        }
      }
      // if (segmentData.index === 3 && segmentData.polygonIndex === 0 && !segmentData.isVertex) {
      //   if (oldEditedVertex) {
      //     coordinates[segmentData.polygonIndex][segmentData.ringIndex][0][1] = coordinates[segmentData.polygonIndex][segmentData.ringIndex][0][1] + vertex[1] - oldEditedVertex[1]
      //     coordinates[segmentData.polygonIndex][segmentData.ringIndex][3][1] = coordinates[segmentData.polygonIndex][segmentData.ringIndex][3][1] + vertex[1] - oldEditedVertex[1]
      //     if (coordinates[1]) {
      //       coordinates[1][segmentData.ringIndex][0][1] = coordinates[1][segmentData.ringIndex][0][1] + vertex[1] - oldEditedVertex[1]
      //     }
      //   }
      // }
      // coordinates[segmentData.polygonIndex][segmentData.ringIndex][segmentData.index] = vertex
      // if (segmentData.index === 0) {
      //   coordinates[segmentData.polygonIndex][segmentData.ringIndex][coordinates[segmentData.polygonIndex][segmentData.ringIndex].length - 1] = vertex
      // }
    }*/
    if (newCoordindates.length >= 2) {
      let points = [];
      if (evt.originalEvent.ctrlKey) {
        points = CubeUtil.getPointsFromFirstAndSecondFace(newCoordindates, geometry.isLeft);
      } else {
        points = CubeUtil.modificationHandlers[cubeMode]["getCubeEightVertexs"](newCoordindates, geometry.isLeft);
      }

      const flag = CubeUtil.updateCoordinatesFromPoints(
        newCoordindates,
        points,
        geometry.isLeft,
        0,
        extent
      );

      if (!flag) {
        return;
      }
    }
    geometry.setCoordinates(newCoordindates);
  }

  /**
   * 获取8个点（仅用于输出八个点坐标和描述）
   * @param coordinates 面坐标
   * @param isLeft 立方体朝向是否朝左
   * @returns {*} 返回8个定点
   */
  static getCubeEightVertexs(coordinates, isLeft) {
    let vertexes = [];
    try {
      if (Cube.cubeMode === 2 || Cube.cubeMode === 1 || Cube.cubeMode === 3) {
        // const cor = coordinates[0].flat(Infinity).filter((_, index) => { return index % 2 == 0 });
        // const minCorX = Math.min(...cor);
        const points = CubeUtil.getPointsFromFrontAndBackFace(coordinates, isLeft);
        const [v0, v1, v2, v3, v4, v5, v6, v7] = points;
        if (isLeft) {
          vertexes = [{
            description: "face-leftbottom",
            x: v0[0],
            y: v0[1],
          }, {
            description: "face-rightbottom",
            x: v1[0],
            y: v1[1],
          }, {
            description: "face-righttop",
            x: v2[0],
            y: v2[1],
          }, {
            description: "face-lefttop",
            x: v3[0],
            y: v3[1],
          }, {
            description: "lefttop",
            x: v4[0],
            y: v4[1],
          }, {
            description: "leftbottom",
            x: v5[0],
            y: v5[1],
          }, {
            description: "evaluatedtop",
            x: v6[0],
            y: v6[1],
          }, {
            description: "evaluatedbottom",
            x: v7[0],
            y: v7[1],
          }];
        } else {
          vertexes = [{
            description: "face-leftbottom",
            x: v0[0],
            y: v0[1],
          }, {
            description: "face-rightbottom",
            x: v1[0],
            y: v1[1],
          }, {
            description: "face-righttop",
            x: v2[0],
            y: v2[1],
          }, {
            description: "face-lefttop",
            x: v3[0],
            y: v3[1],
          }, {
            description: "evaluatedtop",
            x: v4[0],
            y: v4[1],
          }, {
            description: "evaluatedbottom",
            x: v5[0],
            y: v5[1],
          }, {
            description: "righttop",
            x: v6[0],
            y: v6[1],
          }, {
            description: "rightbottom",
            x: v7[0],
            y: v7[1],
          }];
        }
      }
    } catch (error) {
      const v0 = coordinates[0][0][0];
      const v1 = coordinates[0][0][3];
      const v2 = coordinates[0][0][2];
      const v3 = coordinates[0][0][1];
      if (isPrintDescription) {
        vertexes = [{
          description: "face-leftbottom",
          x: v0[0],
          y: v0[1],
        }, {
          description: "face-rightbottom",
          x: v1[0],
          y: v1[1],
        }, {
          description: "face-righttop",
          x: v2[0],
          y: v2[1],
        }, {
          description: "face-lefttop",
          x: v3[0],
          y: v3[1],
        }];
      }
    }

    return vertexes;
  }

  intersectPoint(x, y, tolerance = 3, type = 1) {
    const rings = this._rings.flat(2);
    if(type === 1) {
      const point = rings.find(item => {
        const pointDistance = distance([x, y], item);
        if (pointDistance <= tolerance) {
          return true
        }
      })
      return point;
    }
    
    if(type === 2) { 
      let i = 0;
      let point = null;
      let min = tolerance;
      while(i < rings.length - 1) {
        // 点到线的距离
        const distance = pointDistanceToSegment([x, y], [rings[i], rings[i + 1]]);
        if(distance <= tolerance && distance <= min) {
          min = distance;
          // 点的投影
          point = getProjectionPointOnLine(rings[i], rings[i + 1], [x, y]);
        }
        i++;
      }
      return point;
    }
  }
}

Cube.cubeMode = 1;//1代表标准立方体 2代表前后矩形 //3代表梯形
